home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / WASTE 1.2 / WASTE Demo ƒ / WEDemoScripting.c < prev    next >
Text File  |  1996-05-19  |  9KB  |  339 lines

  1. /*
  2.     WASTE Demo Project:
  3.     Minimal Scripting Support:
  4.     service "get data" and "set data" events
  5.     in which the object descriptor is "contents of selection"
  6.  
  7.     Based on public domain code written by:
  8.     Ed Lai, Apple Computer Inc.
  9.  
  10.     Copyright © 1993-1996 Marco Piovanelli
  11.     All Rights Reserved
  12.  
  13. */
  14.  
  15. #ifndef __AEOBJECTS__
  16. #include <AEObjects.h>
  17. #endif
  18.  
  19. #ifndef __AEREGISTRY__
  20. #include <AERegistry.h>
  21. #endif
  22.  
  23. #ifndef __WEDEMOAPP__
  24. #include "WEDemoIntf.h"
  25. #endif
  26.  
  27. enum {
  28.     kMaxPropLevel    =    2
  29. };
  30.  
  31. typedef DescType PropArray[kMaxPropLevel];
  32.  
  33. static void InitDesc(AEDesc *desc)
  34. {
  35.     desc->descriptorType = typeNull;
  36.     desc->dataHandle = nil;
  37. }
  38.  
  39. static Boolean PropertyOf(const AERecord *spec, short *propLevel, PropArray properties)
  40. {
  41.     AERecord objSpec;
  42.     AEKeyword key;
  43.     DescType theType;
  44.     DescType actualType;
  45.     Size actualSize;
  46.     Boolean retVal = false;
  47.  
  48.     InitDesc(&objSpec);
  49.  
  50.     // if spec is an Apple event (*propLevel = 0), extract its direct parameter
  51.     // otherwise spec is an object specifier record: extract its container param
  52.     key = (*propLevel == 0) ? keyDirectObject : keyAEContainer;
  53.  
  54.     // extract object specifier
  55.     if (AEGetParamDesc(spec, key, typeAERecord, &objSpec) != noErr)
  56.         goto cleanup;
  57.  
  58.     // does this object specifier specify a property?
  59.     if (AEGetParamPtr(&objSpec, keyAEDesiredClass, typeType, &actualType,
  60.                     &theType, sizeof(theType), &actualSize) != noErr)
  61.         goto cleanup;
  62.  
  63.     // sanity check: make sure the key form is formPropertyID
  64.     // this is probably redundant, but checking doesn't hurt
  65.     if (AEGetParamPtr(&objSpec, keyAEKeyForm, typeEnumerated, &actualType,
  66.                     &theType, sizeof(theType), &actualSize) != noErr)
  67.         goto cleanup;
  68.     if (theType != formPropertyID)
  69.         goto cleanup;
  70.  
  71.     // which property does this object specifier specify?
  72.     if (AEGetParamPtr(&objSpec, keyAEKeyData, typeType, &actualType,
  73.                     &theType, sizeof(theType), &actualSize) != noErr)
  74.         goto cleanup;
  75.  
  76.     // bump property level and save property tag into property array
  77.     properties[(*propLevel)++] = theType;
  78.  
  79.     // property of what?
  80.     if (AESizeOfParam(&objSpec, keyAEContainer, &actualType, &actualSize) == noErr)
  81.         if (actualType == typeNull)
  82.             // property of application (i.e., null container): we are done
  83.             retVal = true;
  84.         else if ((actualType == typeObjectSpecifier) && (*propLevel < kMaxPropLevel))
  85.             // property of another object, so do a recursive call
  86.             // unless we have already reached max recursion depth
  87.             retVal = PropertyOf(&objSpec, propLevel, properties);
  88.  
  89. cleanup:
  90.     AEDisposeDesc(&objSpec);
  91.     return retVal;
  92. }
  93.  
  94. OSErr WEGetContentsDesc(long rangeStart, long rangeEnd, Boolean wantStyledText,
  95.         AEDesc *desc, WEReference we)
  96. {
  97.     AEDesc textDesc, stylesDesc, recordDesc;
  98.     OSErr err;
  99.  
  100.     InitDesc(desc);
  101.     InitDesc(&textDesc);
  102.     InitDesc(&stylesDesc);
  103.     InitDesc(&recordDesc);
  104.  
  105.     // allocate a handle to hold the text
  106.     textDesc.dataHandle = NewHandle(0);
  107.     textDesc.descriptorType = typeChar;
  108.     if ((err = MemError()) != noErr)
  109.         goto cleanup;
  110.  
  111.     if (wantStyledText)
  112.     {
  113.         // allocate a handle to hold the styles
  114.         stylesDesc.dataHandle = NewHandle(0);
  115.         stylesDesc.descriptorType = typeScrapStyles;
  116.         if ((err = MemError()) != noErr)
  117.             goto cleanup;
  118.     } // if wantStyledText
  119.  
  120.     // make a copy of the specified text range
  121.     if ((err = WECopyRange(rangeStart, rangeEnd, textDesc.dataHandle,
  122.             (StScrpHandle) stylesDesc.dataHandle, nil, we)) != noErr)
  123.         goto cleanup;
  124.  
  125.     if (wantStyledText)
  126.     {
  127.         // create an Apple event record to hold text + styles
  128.         if ((err = AECreateList(nil, 0, true, &recordDesc)) != noErr)
  129.             goto cleanup;
  130.  
  131.         // add the text descriptor to the record
  132.         if ((err = AEPutParamDesc(&recordDesc, keyAEText, &textDesc)) != noErr)
  133.             goto cleanup;
  134.         AEDisposeDesc(&textDesc);
  135.  
  136.         // add the styles descriptor to the record
  137.         if ((err = AEPutParamDesc(&recordDesc, keyAEStyles, &stylesDesc)) != noErr)
  138.             goto cleanup;
  139.         AEDisposeDesc(&stylesDesc);
  140.  
  141.         // coerce the record into a styled text descriptor
  142.         if ((err = AECoerceDesc(&recordDesc, typeStyledText, desc)) != noErr)
  143.             goto cleanup;
  144.  
  145.     }
  146.     else {
  147.         *desc = textDesc;
  148.         InitDesc(&textDesc);
  149.     }
  150.  
  151.     err = noErr;
  152.  
  153. cleanup:
  154.     AEDisposeDesc(&textDesc);
  155.     AEDisposeDesc(&stylesDesc);
  156.     AEDisposeDesc(&recordDesc);
  157.  
  158.     return err;
  159. }
  160.  
  161. OSErr WESetContentsDesc(long rangeStart, long rangeEnd,
  162.                 const AEDesc *desc, WEReference we)
  163. {
  164.     AEDesc textDesc, stylesDesc, recordDesc;
  165.     OSErr err;
  166.  
  167.     InitDesc(&textDesc);
  168.     InitDesc(&stylesDesc);
  169.     InitDesc(&recordDesc);
  170.  
  171.     // we expect desc type to be either TEXT or STXT
  172.     if (desc->descriptorType == typeStyledText)
  173.     {
  174.         // STYLED TEXT
  175.         // coerce the styled text descriptor to an Apple event record
  176.         if ((err = AECoerceDesc(desc, typeAERecord, &recordDesc)) != noErr)
  177.             goto cleanup;
  178.  
  179.         // extract text + styles from the record
  180.         if ((err = AEGetParamDesc(&recordDesc, keyAEText, typeChar, &textDesc)) != noErr)
  181.             goto cleanup;
  182.         if ((err = AEGetParamDesc(&recordDesc, keyAEStyles, typeScrapStyles, &stylesDesc)) != noErr)
  183.             goto cleanup;
  184.     }
  185.     else {
  186.         // UNSTYLED TEXT
  187.         if ((err = AECoerceDesc(desc, typeChar, &textDesc)) != noErr)
  188.             goto cleanup;
  189.     }
  190.  
  191.     // replace the specified range with the given text
  192.     HLock(textDesc.dataHandle);
  193.     WESetSelection(rangeStart, rangeEnd, we);
  194.     err = WEInsert(*textDesc.dataHandle, GetHandleSize(textDesc.dataHandle),
  195.                 (StScrpHandle) stylesDesc.dataHandle, nil, we);
  196.     HUnlock(textDesc.dataHandle);
  197.  
  198. cleanup:
  199.     AEDisposeDesc(&recordDesc);
  200.     AEDisposeDesc(&textDesc);
  201.     AEDisposeDesc(&stylesDesc);
  202.  
  203.     return err;
  204. }
  205.  
  206. static pascal OSErr HandleGetData(const AppleEvent *ae, AppleEvent *reply, long refCon)
  207. {
  208. #pragma unused (refCon)
  209.  
  210.     AEDesc textDesc;
  211.     DocumentHandle hDocument;
  212.     short propLevel = 0;
  213.     PropArray properties;
  214.     FlavorType requestedType;
  215.     Boolean wantStyledText = false;
  216.     DescType actualType;
  217.     Size actualSize;
  218.     long selStart, selEnd;
  219.     OSErr err;
  220.  
  221.     InitDesc(&textDesc);
  222.  
  223.     // the only Apple event object we recognize is "contents of selection"
  224.     err = errAENoSuchObject;
  225.     if (!PropertyOf(ae, &propLevel, properties) || (propLevel != 2) ||
  226.         (properties[0] != pContents) || (properties[1] != pSelection))
  227.     {
  228.         goto cleanup;
  229.     }
  230.  
  231.     // extract the optional parameter keyAERequestedType, if present
  232.     // The Apple Event Registry says this parameter can be a list
  233.     // of type tags, but in most cases it is just a single tag, as we assume here.
  234.     if (AEGetParamPtr(ae, keyAERequestedType, typeType, &actualType,
  235.         &requestedType, sizeof(requestedType), &actualSize) == noErr)
  236.     {
  237.         wantStyledText = (requestedType == typeStyledText);
  238.     }
  239.  
  240.     // make sure there is a document window in front
  241.     err = errAENoUserSelection;
  242.     if ((hDocument = GetWindowDocument(FrontWindow())) == nil)
  243.     {
  244.         goto cleanup;
  245.     }
  246.  
  247.     // get the selection range
  248.     WEGetSelection(&selStart, &selEnd, (*hDocument)->we);
  249.  
  250.     // create an Apple event descriptor for the selected text
  251.     if ((err = WEGetContentsDesc(selStart, selEnd, wantStyledText,
  252.                 &textDesc, (*hDocument)->we)) != noErr)
  253.     {
  254.         goto cleanup;
  255.     }
  256.  
  257.     // put the text descriptor into the reply event
  258.     if ((err = AEPutParamDesc(reply, keyDirectObject, &textDesc)) != noErr)
  259.     {
  260.         goto cleanup;
  261.     }
  262.  
  263.     // clear result code
  264.     err = noErr;
  265.  
  266. cleanup:
  267.     AEDisposeDesc(&textDesc);
  268.  
  269.     return err;
  270. }
  271.  
  272. static pascal OSErr HandleSetData(const AppleEvent *ae, AppleEvent *reply, long refCon)
  273. {
  274. #pragma unused (reply, refCon)
  275.  
  276.     AEDesc textDesc;
  277.     DocumentHandle hDocument;
  278.     short propLevel = 0;
  279.     PropArray properties;
  280.     long selStart, selEnd;
  281.     OSErr err;
  282.  
  283.     InitDesc(&textDesc);
  284.  
  285.     // the only Apple event object we recognize is "contents of selection"
  286.     err = errAENoSuchObject;
  287.     if (!PropertyOf(ae, &propLevel, properties) || (propLevel != 2) ||
  288.         (properties[0] != pContents) || (properties[1] != pSelection))
  289.     {
  290.         goto cleanup;
  291.     }
  292.  
  293.     // make sure there is a document window in front
  294.     err = errAENoUserSelection;
  295.     if ((hDocument = GetWindowDocument(FrontWindow())) == nil)
  296.     {
  297.         goto cleanup;
  298.     }
  299.  
  300.     // extract the required keyAEData parameter
  301.     if ((err = AEGetParamDesc(ae, keyAEData, typeWildCard, &textDesc)) != noErr)
  302.         goto cleanup;
  303.  
  304.     // get current selection range
  305.     WEGetSelection(&selStart, &selEnd, (*hDocument)->we);
  306.  
  307.     // set the contents of the selection
  308.     if ((err = WESetContentsDesc(selStart, selEnd, &textDesc, (*hDocument)->we)) != noErr)
  309.     {
  310.         goto cleanup;
  311.     }
  312.  
  313.     // clear result code
  314.     err = noErr;
  315.  
  316. cleanup:
  317.     AEDisposeDesc(&textDesc);
  318.  
  319.     return err;
  320. }
  321.  
  322. OSErr InstallCoreHandlers(void)
  323. {
  324.     OSErr err;
  325.  
  326.     if ((err = AEInstallEventHandler(kAECoreSuite, kAEGetData,
  327.             NewAEEventHandlerProc(HandleGetData), 0L, false)) != noErr)
  328.     {
  329.         return err;
  330.     }
  331.  
  332.     if ((err = AEInstallEventHandler(kAECoreSuite, kAESetData,
  333.             NewAEEventHandlerProc(HandleSetData), 0L, false)) != noErr)
  334.     {
  335.         return err;
  336.     }
  337.  
  338.     return noErr;
  339. }